<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2016/9/14 0014
 * Time: 上午 11:01
 */

namespace app\common\service;


use think\Db;
use think\Loader;

class Service
{
    /**
     *
     * @var \think\Model
     */
    public $model = null;
    //模型名称
    protected $modelName = null;
    //模型命名空间
    protected $modelNamespace = '';
//    分页默认大小
    protected $pageSize = 20;
//    查询的字段域
    protected $fields = null;
    //默认按照创建时间排序
    protected $order = "create_time desc";
    //搜索条件
    protected $where = array();
    //查询限制
    protected $limit = null;
    //分组
    protected $group = null;
    //join
    protected $join = null;
    //别名
    protected $alias = null;
   

    /**
     * Service constructor.
     * @param null $modelName
     */
    public function __construct($modelName = null)
    {

        if ($modelName) {
            $this->modelName = $modelName;
        } else {
            //获取类名进行初始化
            $this->modelName = $this->getModelName();
        }
        try {
            //dump($this->modelName);
            $this->model = model($this->modelName);
        } catch (\Exception $e) {
            $this->modelName = null;
            $this->model = null;
        }

        $this->init();
    }


    protected function init()
    {
        //dump($this->model);die;
    }

    /**
     * 获取模型名称
     * @return string
     */
    protected function getModelName()
    {
        $name = get_class($this);
        if ($pos = strrpos($name, '\\')) {//有命名空间
            return substr($name, $pos + 1);
        } else {
            return $name;
        }
    }

    /**
     * @param string $modelName 模型名称
     * @return \think\Model 模型
     */
    public function setModel($modelName)
    {
        if ($modelName) {
            $this->modelName = $modelName;
            $this->model = model($modelName);
        }
        return $this->model;
    }

    /**
     * 析构函数
     */
    public function __destruct()
    {
        $this->clear();

    }

    /**
     * 清除数据
     */
    private function clear()
    {
        $this->fields = null;
        $this->where = array();
        $this->order = "create_time desc";
        $this->limit = null;
        $this->group = null;
    }

    /**
     * 开启事务
     */
    public function startTrans()
    {
        Db::startTrans();
    }

    /**
     * 回滚事务
     */
    public function rollback()
    {
        Db::rollback();
    }

    /**
     * 提交事务
     */
    public function commit()
    {
        Db::commit();
    }


    /**
     * 设置缓存
     */
    public function setCache($name,$value,$prefix='',$time='3600*24')
    {
        $options = [
            // 缓存类型为File
            'type'   => 'File',
            // 缓存有效期为一天
            'expire' => $time,
            //缓存前缀
            'prefix' => $prefix,
            // 指定缓存目录
            'path'   => APP_PATH.'catch',
        ];
        // 设置缓存数据
        cache($name, $value,$options);
        return $this;
    }

    /**
     * 读取缓存
     */
    public function getCache($name,$prefix='')
    {
        // 获取缓存数据
        if($prefix){
            $value=cache($prefix.'_'.$name);
        }else{
            $value=cache($name);
        }

        return $value;
    }

    /**
     * 删除缓存
     */
    public function delCache($name,$prefix='')
    {
        // 删除缓存数据
        if($prefix){
            cache($prefix.'_'.$name,null);
        }else{
            cache($name,null);
        }
        
        return $this;
    }

    /**
     * 增加数据
     * @param array $data 可以是数组格式/模型对象
     * @param bool $validate true|场景名称
     * @return array
     */
    public function add($data = [], $validate = false)
    {
        //判断是否是模型对象
        $model = null;
        if ($data instanceof \Think\Model) {
            $model = $data;
        } else {
            $model = $this->model;
            $model->data($data);
        }
        //声明是添加数据
        $model = $model->isUpdate(false);
        if ($validate) {
            $validateRes = $this->validateData($data, $validate);
            if ($validateRes) {
                return $this->errorResult($validateRes);
            }
        }

        $res = $model->save();
        if ($res) {
            $result = $this->successResult("add_success");
            $result['id'] = $model->id;
            return $result;
        } else {
            return $this->errorResult("add_error");
        }

    }


    /**
     * 自动验证数据
     * @access protected
     * @param array $data 验证数据
     * @return bool
     */
    protected function validateData($data = [], $validate = false)
    {

        if ($validate === true) {
            $validateUtil = Loader::validate($this->modelName);
        } else if (is_string($validate)) {
            if (strpos($validate, '.')) {
                list($name, $scene) = explode('.', $validate);
            }
            $validateUtil = Loader::validate($name);
            if (!empty($scene)) {
                $validateUtil->scene($scene);
            }
        }

        if (!$validateUtil->check($data)) {
            return $validateUtil->getError();
        } else {
            return false;
        }
    }

    /**
     * 修改数据
     * @param array $data 数据  如果数据中含有id  把id作为条件
     * @param bool $validate 验证  是否进行自动验证
     * @param array $where 条件 修改条件
     * @return array  数组
     */
    public function update($data = [], $validate = false, $where = [])
    {
        //判断是否是模型对象
        $model = null;
        if ($data instanceof \Think\Model) {//根据模型实例修改
            $model = $data;
            //声明是修改数据
            $model = $model->isUpdate(true);
            if ($validate) {
                $validateRes = $this->validateData($data, $validate);
                if ($validateRes) {
                    return $this->errorResult($validateRes);
                }
            }
            $res = $model->save();


        } else {
            $model = $this->model;
            if ($data['id'] && empty($where)) {
                $where['id'] = $data['id'];
                unset($data['id']);
            }
            if (empty($where)) {
                return $this->errorResult("修改条件为空！");
            }
            //声明是修改数据
            $model = $model->isUpdate(true);
            if ($validate) {
                $validateRes = $this->validateData($data, $validate);
                if ($validateRes) {
                    return $this->errorResult($validateRes);
                }
            }

            $res = $model->save($data, $where);

        }

        if ($res) {
            return $this->successResult("update_success");
        } else {
            return $this->errorResult("update_erroe");
        }
    }

    /**
     * 模型实例
     * 添加或修改数据数据，自动识别
     * 1.实例化模型后调用save方法表示新增；
     * 2.查询数据后调用save方法表示更新；
     * 3.调用模型的save方法后表示更新；
     * @param $model
     * @return array
     */
    public function addAndUpdate($model = null, $validate = false)
    {
        if ($model instanceof \Think\Model) {
            if ($validate) {
                $validateRes = $this->validateData($model->getData(), $validate);
                if ($validateRes) {
                    return $this->errorResult($validateRes);
                }
            }
            $res = $model->save();

            if ($res) {
                return $this->successResult("update_success");
            } else {
                return $this->errorResult("update_error");
            }
        } else {
            return $this->errorResult("传入数据不是模型的实例！");
        }


    }


    /**
     * 删除数据
     * @param $where
     * @return array
     * @throws \think\Exception
     */
    public function delete($where)
    {
        if (!is_array($where)) {
            $where = array('id' => $where);
        }
        $this->where($where);
        
        $res = $this->getQuery()->delete();
        if ($res) {
            return $this->successResult("delete_success");
        } else {
            return $this->errorResult("delete_error");
        }
    }

    /**
     * @return \think\db\Query
     */
    protected function getQuery()
    {
        $query = $this->model->where($this->where);
        if ($this->fields) {
            $query = $query->field($this->fields);
        }
        if ($this->limit) {
            $query = $query->limit($this->limit);
        }
        if ($this->group) {
            $query = $query->group($this->group);
        }
        if ($this->order) {
            $query = $query->order($this->order);
        }
        if ($this->join) {
            $query = $query->join($this->join,$condition = null, $type = 'LEFT');
        }
        if ($this->alias) {
            $query = $query->alias($this->alias);
        }
        return $query;
    }


    /**
     * 设置查询字段  格式参考tp5.0
     * @param $fields
     * @return $this
     */
    public function fields($fields)
    {
        $this->fields = $fields;
        return $this;
    }

    /**
     * 排序
     * @param string $order
     * @return $this
     */
    public function order($order = 'create_time desc')
    {
        $this->order = $order;
        return $this;
    }

    /**
     * @param $group
     * @return $this
     */
    public function group($group=null){
        $this->group=$group;
        return $this;
    }

    /**
     * @param $fields
     * @return $this
     */
    public function count($fields='*'){
        $query=$this->getQuery();
        return $query->count($fields);
    }

    /**
     * 查询条件：建议数组格式
     * @param $where
     * @return $this
     */
    public function where($where)
    {
        $this->where = array_merge($this->where,$where);
        return $this;
    }


    /**
     * 查询限制
     * @param int $limit
     * @return $this
     */
    public function limit($limit = 1000)
    {
        $this->limit = $limit;
        return $this;
    }
    /**
     * join查询
     * @param string $join
     * @return $this
     */
    public function join($join)
    {
        $this->join =$join;
        return $this;
    }

    /**
     * 表起别名
     * @param string $alias
     * @return $this
     */
    public function alias($alias)
    {
        $this->alias = $alias;
        return $this;
    }

    /**
     * 获取一条数据
     * @param $where
     * @return static
     */
    public function find($where = [])
    {
        if (is_array($where)) {
            $this->where($where);
        }else if(is_string($where)) {
            $this->where['id']=$where;//指定id查询
        }else {
            return false;
        }
        $query = $this->getQuery();
        $this->clear();
        return $query->find();
    }


    /**
     * 分页查询数据
     * @param $where
     * @param bool $pageSize
     * @return array
     */
    public function page($where = array(), $page=1,$pageSize = 10)
    {
        // 条件合并
        if (is_array($where)) {
            $this->where($where);
        }
        $query = $this->getQuery();
        if ($pageSize) {
            $this->pageSize = $pageSize;
        }
        $list = $query->paginate($this->pageSize,true,['page'=>$page]);

        // 获取分页显示
        $page = $list->render();
        $this->clear();
        return ['list' => $list, 'page' => $page];
    }


    /***
     * @param array $where
     * @return false|\PDOStatement|string|\think\Collection
     */
    public function select($where = array())
    {
        // 条件合并
        if (is_array($where)) {
            $this->where($where);
        }
        $query = $this->getQuery();
        $this->clear();
        return $query->select();

    }

    /**
     * 返回结果
     * @param $code
     * @param $msg
     * @return array
     */
    public function getResult($code, $msg = '', $data = array())
    {
        return array('code' => $code, 'msg' => $msg, 'data' => $data);
    }

    /**
     * 成功返回结果
     * @param $msg
     * @return array
     */
    public function successResult($msg = "success", $data = array())
    {
        return $this->getResult(1, $msg, $data);
    }

    /**
     * 错误返回结构
     * @param $msg
     * @return array
     */
    public function errorResult($msg = "error", $data = array())
    {
        return $this->getResult(0, $msg, $data);
    }

    public function loginResult($msg = "no login", $data = array())
    {
        return $this->getResult(2, $msg, $data);
    }

    /**
     * 判断是否是成功的消息
     * @param array $res
     * @return bool
     */
    protected function isSuccess($res = ['code' => 0])
    {
        if ($res['code'] == 1) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是失败的消息
     * @param array $res
     * @return bool
     */
    protected function isError($res = ['code' => 0])
    {
        if ($res['code'] == 1) {
            return false;
        }
        return true;
    }
}